package py.progweb.sgc.gui.server.utils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.log4j.Logger;

import py.progweb.sgc.gui.shared.dialogmodel.DataRecord;
import py.progweb.sgc.manager.ABMManagerLocal;
import py.progweb.sgc.model.EntidadBase;

/**
 * Funciones de manipulación de entity beans
 * 
 * @author jtalavera
 *
 */
public class EntityUtil {
	
	/**
	 * Convierte una lista de entities a una lita de DataRecords
	 * 
	 * @param entities
	 * @return
	 * @throws Exception
	 */
	
	public static List<DataRecord> entities2DataRecords(List<? extends EntidadBase> entities) throws Exception {
		ArrayList<DataRecord> records = new ArrayList<DataRecord>();
		
		for(EntidadBase e : entities)
			records.add(entity2DataRecord(e));
		
		return records;
	}
	
	/**
	 * Convierte un entity a un DataRecord
	 * @param entity
	 * @return
	 * @throws Exception
	 */
	public static DataRecord entity2DataRecord(EntidadBase entity) throws Exception {
		return entity2DataRecord(entity, null, new DataRecord());
	}
	
	/**
	 * Copia recursivamente los atributos de un entity como atributos de un DataRecord
	 * 
	 * @param entity
	 * @param parentName
	 * @param dr
	 * @return
	 * @throws Exception
	 */
	private static DataRecord entity2DataRecord(EntidadBase entity, String parentName, DataRecord dr) throws Exception {
		
		BeanUtilsBean utils = BeanUtilsBean.getInstance();
		String lParentName = parentName == null ? "" : parentName + ".";
		
		dr.setPK(entity.getPK());
		dr.setClassName(entity.getClass().getName());
		
		 try {
			Map properties = utils.describe(entity);
		
			for (Object field : properties.keySet()) {
				Object value = PropertyUtils.getProperty(entity, field.toString());
				
				if (value == null || "class".equals(field) || value instanceof Set || value instanceof List)
					continue;
				
				if (value instanceof EntidadBase)
					entity2DataRecord((EntidadBase)value, lParentName + field.toString(), dr);
				else 
					dr.setAtributo(lParentName + field.toString(), value);
					
			}
						
		} catch (Exception e) {
			e.printStackTrace();
			throw e;
		} 
		
		return dr;
	}
	
	public static List<? extends EntidadBase> dataRecords2Entities(List<DataRecord> drs, ABMManagerLocal mgr) throws Exception {
		ArrayList<EntidadBase> entities = new ArrayList<EntidadBase>();
		
		for(DataRecord dr : drs) 
			entities.add(dataRecord2Entity(dr, mgr));
		
		return entities;
	}
	
	/**
	 * Convierte un DataRecord a un entity bean
	 * @param dr
	 * @param mgr
	 * @return
	 * @throws Exception 
	 */
	public static EntidadBase dataRecord2Entity(DataRecord dr, ABMManagerLocal mgr) throws Exception {		
		//Logger logger = Logger.getLogger(this.getClass());
		Class c = Class.forName(dr.getClassName());
		EntidadBase entity = mgr.buscar(c, (Serializable)dr.getPK());
		return mezclar(entity,dr,null);
	}
	

	private static EntidadBase mezclar(EntidadBase entity, DataRecord dr, String parentName) throws Exception {
		BeanUtilsBean utils = BeanUtilsBean.getInstance();
		String lParentName = parentName == null ? "" : parentName + ".";
		
		 try {
			Map properties = utils.describe(entity);
		
			for (Object field : properties.keySet()) {
				Object value = PropertyUtils.getProperty(entity, field.toString());
				
				if (value == null || "class".equals(field) || value instanceof Set || value instanceof List)
					continue;
				
				if (value instanceof EntidadBase)
					mezclar((EntidadBase)value, dr,lParentName + field.toString());
				else 
					utils.setProperty(entity, field.toString(), dr.getAtributo(lParentName + field.toString()));
			}
						
		} catch (Exception e) {
			e.printStackTrace();
			throw e;
		} 
		
		return entity;
	}
}
